package org.breezeiot.protodecode.controller;

import com.alibaba.fastjson.JSON;
import org.breezeiot.protodecode.protocol.*;
import org.breezeiot.protodecode.protocol.chargingpile.BaseFrame;
import org.breezeiot.protodecode.protocol.chargingpile.MsgDcsResult;
import org.breezeiot.protodecode.protocol.chargingpile.ProtocolJuhuaHandle;
import org.breezeiot.protodecode.component.Dictionary;
import org.breezeiot.protodecode.dataobject.CdIotUpData;
import org.breezeiot.protodecode.dataobject.DyIotUpData;
import org.breezeiot.protodecode.protocol.qgdw3761.ProtocolGW09Handle;
import org.breezeiot.protodecode.protocol.xintian.ProtocolXinTianHandle;
import org.breezeiot.protodecode.utils.ProtocolUtils;
import org.breezeiot.protodecode.utils.StringUtil;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
public class ProtocolController {

    @GetMapping("/")
    public String index(Model model) {
        // 初始化字典
        if(Dictionary.DICT.isEmpty()) {
            Dictionary.init();
        }
        return "index";
    }

    @PostMapping("/parse")
    @ResponseBody
    public Map<String, Object> parseProtocol(@RequestParam String content, @RequestParam String protocolType) {
        Map<String, Object> result = new HashMap<>();
        
        if (StringUtil.isEmpty(content)) {
            result.put("success", false);
            result.put("message", "要解析的报文不能为空");
            return result;
        }
        
        try {
            String jsonResult = "";
            switch (protocolType) {
                case "chargingPile":
                    jsonResult = parseChargingPileProtocol(content);
                    break;
                case "cjt188":
                    jsonResult = parseCjt188Protocol(content);
                    break;
                case "qgdw3761":
                    jsonResult = parseQgdw3761Protocol(content);
                    break;
                case "dlt64507":
                    jsonResult = parseDlt64507Protocol(content);
                    break;
                case "dyIot":
                    jsonResult = parseDyIotProtocol(content);
                    break;
                case "cdIot":
                    jsonResult = parseCdIotProtocol(content);
                    break;
                case "waterCollector":
                    jsonResult = parseWaterCollectorProtocol(content);
                    break;
                case "xintianWater":
                    jsonResult = parseXintianWaterProtocol(content);
                    break;
                default:
                    result.put("success", false);
                    result.put("message", "不支持的协议类型");
                    return result;
            }
            
            // 替换字典
            String replacedJson = replaceWithDictionary(jsonResult);
            
            result.put("success", true);
            result.put("jsonResult", replacedJson);
            result.put("formattedJson", formatJsonWithTwoSpaces(replacedJson));
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", errInfo(e));
        }
        
        return result;
    }

    public String replaceWithDictionary(String input) {
        if(Dictionary.DICT.isEmpty()) {
            Dictionary.init();
        }
        for (Map.Entry<String, String> entry : Dictionary.DICT.entrySet()) {
            input = input.replace(entry.getKey(), entry.getValue());
        }
        return input;
    }

    /**
     * 使用紧凑格式格式化JSON，只在必要时换行
     */
    private String formatJsonWithTwoSpaces(String jsonString) {
        try {
            // 先解析JSON确保格式正确
            Object jsonObj = JSON.parse(jsonString);
            // 先生成紧凑格式的JSON
            String compactJson = JSON.toJSONString(jsonObj, new com.alibaba.fastjson.serializer.SerializerFeature[]{
                com.alibaba.fastjson.serializer.SerializerFeature.WriteMapNullValue,
                com.alibaba.fastjson.serializer.SerializerFeature.WriteNullListAsEmpty,
                com.alibaba.fastjson.serializer.SerializerFeature.WriteNullStringAsEmpty
            });
            
            // 手动添加适当的换行和缩进，使JSON更紧凑
            return formatCompactJson(compactJson);
        } catch (Exception e) {
            // 如果格式化失败，返回原始字符串
            return jsonString;
        }
    }
    
    /**
     * 手动格式化JSON，使其更紧凑
     */
    private String formatCompactJson(String json) {
        StringBuilder result = new StringBuilder();
        int indentLevel = 0;
        boolean inString = false;
        boolean escapeNext = false;
        
        for (int i = 0; i < json.length(); i++) {
            char c = json.charAt(i);
            
            if (escapeNext) {
                result.append(c);
                escapeNext = false;
                continue;
            }
            
            if (c == '\\') {
                escapeNext = true;
                result.append(c);
                continue;
            }
            
            if (c == '"' && !escapeNext) {
                inString = !inString;
                result.append(c);
                continue;
            }
            
            if (inString) {
                result.append(c);
                continue;
            }
            
            switch (c) {
                case '{':
                case '[':
                    result.append(c);
                    indentLevel++;
                    // 检查下一个字符，如果不是结束符，则换行
                    if (i + 1 < json.length()) {
                        char nextChar = json.charAt(i + 1);
                        if (nextChar != '}' && nextChar != ']') {
                            result.append('\n').append(getIndent(indentLevel));
                        }
                    }
                    break;
                    
                case '}':
                case ']':
                    indentLevel--;
                    // 检查前面是否有内容，如果有且不是换行，则先换行
                    if (result.length() > 0 && result.charAt(result.length() - 1) != '\n') {
                        result.append('\n').append(getIndent(indentLevel));
                    } else if (result.length() > 0 && result.charAt(result.length() - 1) == '\n') {
                        // 如果前面是换行，则添加缩进
                        result.append(getIndent(indentLevel));
                    }
                    result.append(c);
                    break;
                    
                case ',':
                    result.append(c);
                    // 检查下一个字符，如果不是结束符，则换行
                    if (i + 1 < json.length()) {
                        char nextChar = json.charAt(i + 1);
                        if (nextChar != '}' && nextChar != ']') {
                            result.append('\n').append(getIndent(indentLevel));
                        }
                    }
                    break;
                    
                case ':':
                    result.append(c).append(' ');
                    break;
                    
                default:
                    result.append(c);
                    break;
            }
        }
        
        return result.toString();
    }
    
    /**
     * 生成指定层级的缩进
     */
    private String getIndent(int level) {
        StringBuilder indent = new StringBuilder();
        for (int i = 0; i < level; i++) {
            indent.append("  "); // 2个空格
        }
        return indent.toString();
    }

    public static String errInfo(Exception e) {
        StringWriter sw = null;
        PrintWriter pw = null;
        try {
            sw = new StringWriter();
            pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            pw.flush();
            sw.flush();
            return sw.toString();
        } finally {
            if (sw != null) {
                try {
                    sw.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (pw != null) {
                pw.close();
            }
        }
    }

    private String parseChargingPileProtocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        BaseFrame frame = ProtocolJuhuaHandle.validateMessage(buf);
        if (frame == null) {
            throw new Exception("报文格式有误");
        }
        MsgDcsResult result = ProtocolJuhuaHandle.decoder(frame);
        return formatJsonWithTwoSpaces(JSON.toJSONString(result));
    }

    private String parseCjt188Protocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        PointCommInfo pointCommInfo = Protocol188Util.parseCommand(buf);
        if (pointCommInfo == null) {
            throw new Exception("报文格式有误");
        }
        return formatJsonWithTwoSpaces(JSON.toJSONString(pointCommInfo));
    }

    private String parseQgdw3761Protocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        MsgDcsResult result = ProtocolGW09Handle.decoder(buf);
        if (result == null) {
            throw new Exception("报文格式有误");
        }
        return formatJsonWithTwoSpaces(JSON.toJSONString(result));
    }

    private String parseDlt64507Protocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        PointCommInfo pointCommInfo = Protocol645_07Util.parseCommand(buf);
        if (pointCommInfo == null) {
            throw new Exception("报文格式有误");
        }
        return formatJsonWithTwoSpaces(JSON.toJSONString(pointCommInfo));
    }

    private String parseDyIotProtocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        DyIotUpData dyIotUpData = ProtocolDyIotWaterUtil.parseMessage(buf);
        if (dyIotUpData == null) {
            throw new Exception("报文格式有误");
        }
        return formatJsonWithTwoSpaces(JSON.toJSONString(dyIotUpData));
    }

    private String parseCdIotProtocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        CdIotUpData cdIotUpData = ProtocolCdIotWaterUtil.parseMessage(buf);
        if (cdIotUpData == null) {
            throw new Exception("报文格式有误");
        }
        return formatJsonWithTwoSpaces(JSON.toJSONString(cdIotUpData));
    }

    private String parseWaterCollectorProtocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        List<Object> result = ProtocolWaterMeterCollectorUtil.parseMessage(buf);
        if (result == null || result.isEmpty()) {
            throw new Exception("报文格式有误");
        }
        return formatJsonWithTwoSpaces(JSON.toJSONString(result));
    }

    private String parseXintianWaterProtocol(String content) throws Exception {
        content = content.replaceAll("\n", "");
        byte[] buf = ProtocolUtils.message2Bytes(content);
        MsgDcsResult result = ProtocolXinTianHandle.decoder(buf);
        if (result == null) {
            throw new Exception("报文格式有误");
        }
        return formatJsonWithTwoSpaces(JSON.toJSONString(result));
    }
} 